package com.qqtech.qquan.order.service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.qqtech.core.common.constant.CoreConst;
import com.qqtech.core.common.enums.YesNoEnum;
import com.qqtech.core.common.util.ArithUtil;
import com.qqtech.core.common.util.StringUtil;
import com.qqtech.core.common.util.TimeUtil;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.model.Result;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.mall.model.MallShop;
import com.qqtech.qquan.mall.service.MallShopService;
import com.qqtech.qquan.order.dao.OrderBaseDao;
import com.qqtech.qquan.order.enums.OrderBaseOrderStatusDictEnum;
import com.qqtech.qquan.order.enums.OrderBaseOrderTypeDictEnum;
import com.qqtech.qquan.order.enums.OrderBasePayStatusDictEnum;
import com.qqtech.qquan.order.enums.OrderBasePayTypeDictEnum;
import com.qqtech.qquan.order.enums.OrderPayWayDictEnum;
import com.qqtech.qquan.order.model.OrderBase;
import com.qqtech.qquan.order.model.OrderBaseQuery;
import com.qqtech.qquan.order.model.OrderBaseVo;
import com.qqtech.qquan.user.service.UserMoneyLogService;

@Service
public class OrderBaseServiceImpl extends BaseServiceImpl<OrderBase> implements OrderBaseService {
	public static final Logger log = LoggerFactory.getLogger(OrderBaseServiceImpl.class);
	@Resource
	private OrderPayLogService orderPayLogService;
	@Resource
	private OrderBaseDao orderBaseDao;
	@Resource
	private UserMoneyLogService userMoneyLogService;
	@Resource
	private MallShopService mallShopService;

	@Override
	protected BaseDao<OrderBase> getBaseDao() {
		return orderBaseDao;
	}

	@Override
	public OrderBaseVo getByOrderNo(java.lang.String orderNo) {
		return orderBaseDao.getByOrderNo(orderNo);
	}

	@Override
	public Result checkForPay(String orderNo, Integer userId) {
		Result result = new Result();
		if (StringUtil.isBlank(orderNo) || userId == null || userId.intValue() == 0) {
			result.addErr("当前订单或登录人信息有误");
			return result;
		}
		OrderBase orderBase = orderBaseDao.getByOrderNo(orderNo);
		if (orderBase == null) {
			result.addErr("订单不存在");
			return result;
		}
		if (OrderBaseOrderStatusDictEnum.UNCOMPLETED.getCode() != orderBase.getOrderStatus().intValue()) {
			result.addErr("订单状态不是未完成");
			return result;
		}
		if (OrderBasePayStatusDictEnum.UNPAYED.getCode() != orderBase.getPayStatus().intValue()) {
			result.addErr("付款状态不是未付款");
			return result;
		}
		if (OrderBasePayTypeDictEnum.ONLINE.getCode() != orderBase.getPayType().intValue()) {
			result.addErr("该订单没有选择在线付款");
			return result;
		}
		BigDecimal total = orderBase.getTotal();
		if (total == null || total.compareTo(BigDecimal.ZERO) <= 0) {
			result.addErr("该订单不需要再付款");
			return result;
		}
		BigDecimal payed = orderPayLogService.getPayedByOrderNo(orderNo, null);
		if (total.compareTo(payed) <= 0) {
			result.addErr("该订单已支付完成");
			return result;
		}
		BigDecimal needPay = total.subtract(payed);
		if (needPay.compareTo(BigDecimal.ZERO) <= 0) {
			result.addErr("该订单已支付完成");
			return result;
		}
		double needPayTotle = ArithUtil.roundMoney(needPay);
		if (needPayTotle <= 0) {
			result.addErr("该订单已无须再支付");
			return result;
		}
		Timestamp autoExpireAt = orderBase.getAutoExpireAt();
		if (autoExpireAt == null) {
			result.addErr("订单数据异常，请稍后再试");
			return result;
		}
		int leftSeconds = TimeUtil.secondsOfTwo(TimeUtil.now(), autoExpireAt);
		if (leftSeconds <= 0) {
			result.addErr("订单已超过规定的支付时间");
			return result;
		}
		// 是否使用圈币支付
		int useQuanPay = YesNoEnum.NO.getCode();
		// 还可以使用圈币支付的额度
		double mayPayWithQuan = 0;
		// 商家让利的圈币比例
		BigDecimal shopRate = BigDecimal.ZERO;
		// 平台让利的圈币比例
		BigDecimal qqRate = BigDecimal.ZERO;
		if (orderBase.getOrderType() != null
				&& OrderBaseOrderTypeDictEnum.QSHOP.getCode() == orderBase.getOrderType().intValue()) {
			Integer shopId = orderBase.getShopId();
			if (shopId != null) {
				MallShop mallShop = mallShopService.getById(shopId);
				if (mallShop != null) {
					if (mallShop.getIsUseQuanPay() != null) {
						useQuanPay = mallShop.getIsUseQuanPay();
						shopRate = mallShop.getQuanPayRate() == null ? BigDecimal.ZERO : mallShop.getQuanPayRate();
						qqRate = mallShop.getQqQuanPayRate() == null ? BigDecimal.ZERO : mallShop.getQqQuanPayRate();
						if (shopRate.add(qqRate).compareTo(BigDecimal.ONE) >= 0) {
							qqRate = BigDecimal.ONE.subtract(shopRate);
						}
						// 原价可以使用圈币支付的额度
						BigDecimal totalMayWithQuan = total.multiply(shopRate.add(qqRate));
						// 已用圈币支付了的额度
						BigDecimal payedWithQuan = orderPayLogService.getPayedByOrderNo(orderNo,
								OrderPayWayDictEnum.QUAN);
						mayPayWithQuan = ArithUtil.roundMoney(totalMayWithQuan.subtract(payedWithQuan)
								.multiply(BigDecimal.TEN.multiply(BigDecimal.TEN)));
					}
				}
			}
		}
		/************************************************************/
		// 除抵扣外，还需在线支付额
		double needPayOnline = 0;
		// 抵扣值
		double deduction = 0;
		// 个人有效余额
		double myMoney = ArithUtil.round(userMoneyLogService.getValidMoney(userId) * CoreConst.VALUE_CORE_MONEYRATE, 0);
		// 个人有效圈币
		double myQuan = ArithUtil.round(userMoneyLogService.getValidQuan(userId) * CoreConst.VALUE_CORE_MONEYRATE, 0);
		// 需要完全抵扣的余额值(还需支付的订单额)
		double needPay100 = ArithUtil.round(needPayTotle * CoreConst.VALUE_CORE_MONEYRATE, 0);
		/************************************************************/
		//1、勾选圈币支付时
		int isAllQuan = YesNoEnum.NO.getCode();//是否圈币就能完全抵扣
		int isAllQNM = YesNoEnum.NO.getCode();//是否圈币加余额就能完全抵扣
		//只勾选圈币
		double type1Quan = 0;
		double type1Online = 0;
		//勾选圈币的同时勾选余额
		double type2Money = 0;
		double type2Online = 0;
		
		//判断圈币(以及余额情况)
		if(mayPayWithQuan>=needPay100){//在允许完全抵扣范围内
			if (myQuan >= needPay100) {
				isAllQuan = YesNoEnum.YES.getCode();
				type1Quan = needPay100;
				type1Online = 0;
			} else {
				type1Quan = myQuan;
				type1Online = ArithUtil.round(new Double(needPay100 - myQuan) / CoreConst.VALUE_CORE_MONEYRATE, 2);
			}
			//同时勾选余额
			if (myMoney >= (needPay100 - type1Quan)) {
				isAllQNM = YesNoEnum.YES.getCode();
				type2Money = needPay100 - type1Quan;
				type2Online = 0;
			} else {
				type2Money = myMoney;
			}
			type2Online = ArithUtil.round(new Double(needPay100 -type1Quan- type2Money) / CoreConst.VALUE_CORE_MONEYRATE, 2);
		}else{
			if (myQuan >= mayPayWithQuan) {
				type1Quan = mayPayWithQuan;
			} else {
				type1Quan = myQuan;
			}
			type1Online = ArithUtil.round(new Double(needPay100 - type1Quan) / CoreConst.VALUE_CORE_MONEYRATE, 2);
			//同时勾选余额
			if (myMoney >= (needPay100 - type1Quan)) {
				isAllQNM = YesNoEnum.YES.getCode();
				type2Money = needPay100 - type1Quan;
				type2Online = 0;
			} else {
				type2Money = myMoney;
			}
			type2Online = ArithUtil.round(new Double(needPay100 -type1Quan- type2Money) / CoreConst.VALUE_CORE_MONEYRATE, 2);
		}
		//判断余额情况
		int isAllMoney = YesNoEnum.NO.getCode();//是否余额就能完全抵扣
		double type3Money = 0;
		double type3Online = 0;
		if (myMoney >= needPay100) {
			isAllMoney = YesNoEnum.YES.getCode();
			type3Money = needPay100;
		} else {
			type3Money = myMoney;
			type3Online = ArithUtil.round(new Double(needPay100 - type3Money) / CoreConst.VALUE_CORE_MONEYRATE, 2);
		}
		result.put("useQuanPay", ""+useQuanPay);
		result.put("hasQuan", myQuan>0?""+YesNoEnum.YES.getCode():""+YesNoEnum.NO.getCode());
		result.put("hasMayPayWithQuan", mayPayWithQuan>0?""+YesNoEnum.YES.getCode():""+YesNoEnum.NO.getCode());
		
		result.put("isAllQuan", ""+isAllQuan);
		result.put("isAllMoney", ""+isAllMoney);
		result.put("isAllQNM", ""+isAllQNM);
		result.put("type1Quan", new Double(type1Quan).intValue());
		result.put("type1QuanRMB", ArithUtil.round(new Double(type1Quan) / CoreConst.VALUE_CORE_MONEYRATE, 2));
		result.put("type2Money", new Double(type2Money).intValue());
		result.put("type2MoneyNQuanRMB", ArithUtil.round(new Double(type1Quan+type2Money) / CoreConst.VALUE_CORE_MONEYRATE, 2));
		result.put("type3Money", new Double(type3Money).intValue());
		result.put("type3MoneyRMB", ArithUtil.round(new Double(type3Money) / CoreConst.VALUE_CORE_MONEYRATE, 2));
		result.put("type1Online", type1Online);
		result.put("type2Online", type2Online);
		result.put("type3Online", type3Online);
		result.put("type4Online", needPayTotle);
		result.put("type4Online100", needPay100);
		result.put("shopRate", shopRate);
		result.put("qqRate", qqRate);
		
		
		if (myMoney >= needPay100) {
			deduction = needPay100;
		} else {
			deduction = myMoney;
			needPayOnline = ArithUtil.round(new Double(needPay100 - myMoney) / CoreConst.VALUE_CORE_MONEYRATE, 2);
		}
		result.put("total", "" + ArithUtil.roundMoney(total));
		result.put("payed", "" + ArithUtil.roundMoney(payed));
		result.put("needPayTotle", "" + needPayTotle);
		result.put("needPayOnline", "" + needPayOnline);
		result.put("deduction", new Double(deduction).intValue());
		result.put("deductionMoney", ArithUtil.round(new Double(deduction) / CoreConst.VALUE_CORE_MONEYRATE, 2));
		// 抵扣值是否为0，用于是否展示抵扣可选
		result.put("isDeduction", deduction > 0 ? "" + YesNoEnum.YES.getCode() : "" + YesNoEnum.NO.getCode());
		result.put("deductionAll", needPayOnline <= 0 ? "" + YesNoEnum.YES.getCode() : "" + YesNoEnum.NO.getCode());
		result.put("orderNo", orderNo);
		result.put("title", StringUtil.isBlank(orderBase.getTitle()) ? "圈圈订单" : orderBase.getTitle());
		result.put("leftSeconds", leftSeconds);
		result.put("buyerId", "" + orderBase.getBuyerId());
		return result;
	}

	@Override
	public Page<OrderBaseVo> queryPageListAdmin(OrderBaseQuery query, Pageable pageable) {
		return orderBaseDao.queryPageListAdmin(query, pageable);
	}

	@Override
	public List<OrderBaseVo> queryList4Excel(OrderBaseQuery query, Pageable pageable) {
		return orderBaseDao.queryList4Excel(query, pageable);
	}

	@Override
	public Page<OrderBaseVo> queryPageBySupplier(OrderBaseQuery query, Pageable pageable) {
		return orderBaseDao.queryPageBySupplier(query, pageable);
	}

	@Override
	public int queryCountBySupplier(OrderBaseQuery query) {
		return orderBaseDao.queryCountBySupplier(query);
	}

	@Override
	public Page<OrderBaseVo> queryPageBySendDeliveryUser(OrderBaseQuery query, Pageable pageable) {
		return orderBaseDao.queryPageBySendDeliveryUser(query, pageable);
	}

	@Override
	public int queryCountBySendDeliveryUser(OrderBaseQuery query) {
		return orderBaseDao.queryCountBySendDeliveryUser(query);
	}

	@Override
	public BigDecimal queryTotalPriceByShop(Integer shopId) {
		BigDecimal totalPrice = BigDecimal.ZERO;
		if (shopId != null) {
			OrderBaseQuery query = new OrderBaseQuery();
			query.setShopId(shopId);
			query.setOrderType(OrderBaseOrderTypeDictEnum.QSHOP.getCode());
			query.setOrderStatus(OrderBaseOrderStatusDictEnum.COMPLETED.getCode());
			totalPrice = orderBaseDao.queryTotalPriceByShop(query);
			if (totalPrice == null) {
				totalPrice = BigDecimal.ZERO;
			}
		}
		return totalPrice;

	}

	@Override
	public int updateSellerTotalById(OrderBaseQuery query) {
		return this.orderBaseDao.updateSellerTotalById(query);
	}

	@Override
	public BigDecimal getSumSellerTotal(OrderBaseQuery query) {
		return orderBaseDao.getSumSellerTotal(query);
	}

	@Override
	public BigDecimal getSumTotal4Admin(OrderBaseQuery query) {
		return orderBaseDao.getSumTotal4Admin(query);
	}

	@Override
	public List<OrderBaseVo> queryOrderCountByUserIds(List<Integer> userIds) {
		OrderBaseQuery orderBaseQuery = new OrderBaseQuery();
		orderBaseQuery.setUserIds(userIds);
		return orderBaseDao.queryOrderCountByUserIds(orderBaseQuery);
	}
}